package com.rxh.service;

import com.rxh.exception.PayException;
import com.rxh.pojo.core.*;
import com.rxh.pojo.merchant.MerchantGoods;
import com.rxh.pojo.merchant.MerchantRate;
import com.rxh.pojo.merchant.MerchantRatePercent;
import com.rxh.pojo.merchant.MerchantWebSite;
import com.rxh.pojo.payment.ProductDetail;
import com.rxh.pojo.payment.TradeObject;
import com.rxh.pojo.risk.RiskOrderTrack;
import com.rxh.utils.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: 陈俊雄
 * Date: 2018/9/11
 * Time: 9:16
 * Project: Management
 * Package: com.rxh.service
 */
@Service
public class RecordService {
    @Resource
    private PaymentRecordService paymentRecordService;
    @Resource
    private RSAUtils rsaUtils;

    public void saveOrderTrack(RiskOrderTrack orderTrack) {
        orderTrack.setId(UUID.createKey("core_order_track"));
        paymentRecordService.insertOrderTrack(orderTrack);
    }

    CoreOrder saveAndGetOrder(TradeObject tradeObject, RiskOrderTrack orderTrack, MerchantWebSite merchantWebSite, CoreTradeRate tradeRate, CoreAcquirerAccount acquirerAccount) {
        CoreOrder order = new CoreOrder();
        order.setId(UUID.createKey("core_order"));
        order.setMerId(tradeObject.getMerNo());
        order.setMerOrderId(tradeObject.getBillNo());
        order.setSiteId(merchantWebSite.getId());
        order.setPayMode(tradeObject.getPayMode());
        order.setPayType(tradeObject.getPayType());
        order.setTradeTime(orderTrack.getTradeTime());
        order.setRate(tradeRate.getRate());
        order.setAccountId(acquirerAccount.getId());
        order.setAmount(tradeObject.getAmount());
        order.setCurrency(tradeObject.getCurrency());
        order.setRmbAmount(tradeObject.getAmount().multiply(tradeRate.getRate()));
        order.setBankStatus(SystemConstant.BANK_STATUS_PENDING_PAYMENT);
        paymentRecordService.insertCoreOrder(order);
        return order;
    }

    CoreMerchantOrder saveAndGetMerchantOrder(TradeObject tradeObject, CoreOrder order, MerchantRate merchantRate) {
        CoreMerchantOrder merchantOrder = new CoreMerchantOrder();
        merchantOrder.setId(UUID.createKey("core_merchant_order"));
        merchantOrder.setOrderId(order.getId());
        merchantOrder.setFreight(tradeObject.getFreight());
        merchantOrder.setSourceAmount(tradeObject.getAmount());
        merchantOrder.setSourceCurrency(tradeObject.getCurrency());
        merchantOrder.setReturnUrl(tradeObject.getReturnURL());
        merchantOrder.setNoticeUrl(tradeObject.getNotifyURL());
        merchantOrder.setCustomerId(tradeObject.getCustomerId());
        merchantOrder.setBond(merchantRate.getBailRate().multiply(tradeObject.getAmount()));
        merchantOrder.setDeduct(merchantRate.getRate().multiply(tradeObject.getAmount()));
        paymentRecordService.insertMerchantOrder(merchantOrder);
        return merchantOrder;
    }

    CoreMerchantOrderRmb saveAndGetMerchantOrderRmb(TradeObject tradeObject, CoreOrder order, MerchantRate merchantRate, CoreTradeRate tradeRate) {
        CoreMerchantOrderRmb merchantOrderRmb = new CoreMerchantOrderRmb();
        merchantOrderRmb.setId(UUID.createKey("core_merchant_order_rmb"));
        merchantOrderRmb.setOrderId(order.getId());
        merchantOrderRmb.setSourceRmbAmount(order.getRmbAmount());
        merchantOrderRmb.setSourceRmbBond(merchantRate.getBailRate().multiply(order.getRmbAmount()));
        merchantOrderRmb.setSourceRmbDeduct(merchantRate.getRate().multiply(order.getRmbAmount()));
        paymentRecordService.insertMerchantOrderRmb(merchantOrderRmb);
        return merchantOrderRmb;
    }

    CoreOrderDetail saveAndGetOrderDetail(TradeObject tradeObject, RiskOrderTrack orderTrack, CoreOrder order) {
        CoreOrderDetail orderDetail = new CoreOrderDetail();
        orderDetail.setId(UUID.createKey("core_order_detail"));
        orderDetail.setOrderId(order.getId());
        orderDetail.setFirstName(tradeObject.getShipFirstName());
        orderDetail.setLastName(tradeObject.getShipLastName());
        orderDetail.setAddress(tradeObject.getShipAddress());
        orderDetail.setCity(tradeObject.getShipCity());
        orderDetail.setProvince(tradeObject.getShipState());
        orderDetail.setCountry(tradeObject.getShipCountry());
        orderDetail.setZip(tradeObject.getShipZip());
        orderDetail.setEmail(tradeObject.getShipEmail());
        orderDetail.setPhone(tradeObject.getShipPhone());
        orderDetail.setLang(tradeObject.getLang());
        orderDetail.setRemark(tradeObject.getRemark());
        orderDetail.setIp(tradeObject.getIp());
        orderDetail.setReferer(orderTrack.getRefer());
        paymentRecordService.insertOrderDetail(orderDetail);
        return orderDetail;
    }

    CoreCardholder saveAndGetCardholder(TradeObject tradeObject, CoreOrder order) throws PayException {
        CoreCardholder cardholder = new CoreCardholder();
        cardholder.setId(UUID.createKey("core_cardholder"));
        cardholder.setOrderId(order.getId());
        cardholder.setFirstName(tradeObject.getBillFirstName());
        cardholder.setLastName(tradeObject.getBillLastName());
        cardholder.setAddress(tradeObject.getBillAddress());
        cardholder.setCity(tradeObject.getShipCity());
        cardholder.setProvince(tradeObject.getBillState());
        cardholder.setCountry(tradeObject.getBillCountry());
        cardholder.setZip(tradeObject.getBillZip());
        cardholder.setEmail(tradeObject.getBillEmail());
        cardholder.setPhone(tradeObject.getBillPhone());
        cardholder.setRsa(rsaUtils.encrypt(tradeObject.getCardNo()));
        cardholder.setPayFlag(SystemConstant.PAY_FLAG_LAST);
        cardholder.setPayType(tradeObject.getPayType());
        cardholder.setIssuer(tradeObject.getIssue());
        cardholder.setMd5(DigestUtils.md5Hex(tradeObject.getCardNo()));
        cardholder.setSimpleCard(CardHandle.getSimpleCardNum(tradeObject.getCardNo()));
        cardholder.setVersion(rsaUtils.getRsaVersion());
        paymentRecordService.insertCardholder(cardholder);
        return cardholder;
    }

    CoreCardDetail saveAndGetCardDetail(TradeObject tradeObject, CoreCardholder cardholder) throws PayException {
        CoreCardDetail cardDetail = new CoreCardDetail();
        cardDetail.setId(UUID.createKey("core_card_detail"));
        cardDetail.setCardholderId(cardholder.getId());
        cardDetail.setExpMonth(tradeObject.getExpireMonth());
        cardDetail.setExpYear(tradeObject.getExpireYear());
        cardDetail.setRsa(rsaUtils.encrypt(tradeObject.getSecurityNum()));
        cardDetail.setVersion(null);
        paymentRecordService.insertCardDetail(cardDetail);
        return cardDetail;
    }

    ChannelOrderInfo saveAndGetChannelOrderInfo(CoreOrder order, CoreTradeRate tradeRate, MerchantRatePercent merchantRatePercent, CoreAcquirerAccount acquirerAccount, CoreAcquirerRate acquirerRate) {
        CoreAcquirerAccountParam param = JsonUtils.jsonToPojo(acquirerAccount.getParams(), CoreAcquirerAccountParam.class);
        assert param != null;
        // 通道汇率 = （1 + 商户上抛点数） * 汇率
        BigDecimal channelTransRate = new BigDecimal(1).add(merchantRatePercent.getUpPercent()).multiply(tradeRate.getRate());
        ChannelOrderInfo channelOrderInfo = new ChannelOrderInfo();
        channelOrderInfo.setId(UUID.createKey("channel_order_info"));
        channelOrderInfo.setOrderId(order.getId());
        channelOrderInfo.setMerchantId(String.valueOf(param.getMerNum()));
        // 通道币种
        channelOrderInfo.setChannelCurrency(tradeRate.getTargetCurrency());
        // 通道金额 = 原始金额 * 通道汇率
        channelOrderInfo.setChannelAmount(order.getAmount().multiply(channelTransRate));
        // 通道扣率
        channelOrderInfo.setChannelFeeRate(acquirerRate.getRate());
        // 通道交易手续费 = 订单原始金额 * 通道扣率
        channelOrderInfo.setChannelDeduct(order.getAmount().multiply(acquirerRate.getRate()));
        // 通道保证金
        channelOrderInfo.setChannelBond(null);
        // 通道交易汇率
        channelOrderInfo.setChannelTransRate(channelTransRate);
        // 通道清算汇率
        channelOrderInfo.setChannelSettleRate(null);
        paymentRecordService.insertChannelOrderInfo(channelOrderInfo);
        return channelOrderInfo;
    }

    List<CoreOrderGoods> saveAndGetOrderGoods(List<ProductDetail> productDetails, CoreOrder order) {
        ArrayList<CoreOrderGoods> coreOrderGoodsList = new ArrayList<>();
        productDetails.forEach(productDetail -> {
            CoreOrderGoods orderGoods = new CoreOrderGoods();
            orderGoods.setId(UUID.createKey("core_order_goods"));
            orderGoods.setCurrency(order.getCurrency());
            orderGoods.setOrderId(order.getId());
            orderGoods.setGoodId(Long.valueOf(productDetail.getGoodId()));
            coreOrderGoodsList.add(orderGoods);
        });
        paymentRecordService.insertOrderGoods(coreOrderGoodsList);
        return coreOrderGoodsList;
    }

    List<MerchantGoods> saveAndGetMerchantGoods(TradeObject tradeObject, MerchantWebSite merchantWebSite) {
        List<MerchantGoods> merchantGoodsList = new ArrayList<>();
        List<ProductDetail> productDetails = tradeObject.getProductDetails();
        productDetails.forEach(productDetail -> {
            MerchantGoods merchantGoods = new MerchantGoods();
            merchantGoods.setId(UUID.createKey("merchant_goods"));
            merchantGoods.setName(productDetail.getGoodName());
            merchantGoods.setProductId(productDetail.getGoodId());
            merchantGoods.setCurrency(tradeObject.getCurrency());
            merchantGoods.setPrice(productDetail.getPrice().divide(new BigDecimal(productDetail.getQty()), BigDecimal.ROUND_HALF_UP));
            // 0：旧商品，1：新商品（未添加常量类SystemConstant中）
            merchantGoods.setCurrentFlag((short) 1);
            merchantGoods.setSiteId(merchantWebSite.getId());
            merchantGoodsList.add(merchantGoods);
        });
        paymentRecordService.insertMerchantGoods(merchantGoodsList);
        return merchantGoodsList;
    }

    int updateOrder(CoreOrder order) {
        return paymentRecordService.updateOrderByPrimaryKeySelective(order);
    }
}
